/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#include "DXUT.h"

#include "StoreFragments.h"
#include "DXHelper.h"
#include "SceneBase.h"
#include "LinkedListOIT.h"

/**
*/
StoreFragments::StoreFragments() : m_pPS( NULL )
{
}

/**
*/
StoreFragments::~StoreFragments()
{
}

/**
    @param[in] pDevice        D3D Device
*/
HRESULT StoreFragments::OnCreateDevice( ID3D11Device* pDevice )
{
    HRESULT hr = S_OK;

    // StoreFragments Pixel Shader
    ID3DBlob* pBlob = NULL;
    V_RETURN( CompileShaderFromFile( L"StoreFragments.hlsl", "StoreFragmentsPS", "ps_5_0", &pBlob ) );
    V_RETURN( pDevice->CreatePixelShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &m_pPS ) );
    SAFE_RELEASE( pBlob );

    return hr;    
}

/**
*/
void StoreFragments::OnDestroyDevice()
{
    SAFE_RELEASE( m_pPS );
}

/**
*/
void StoreFragments::OnRender(    ID3D11DeviceContext* pD3DContext, ID3D11Device* pDevice, const DXGI_SURFACE_DESC* pBackBufferDesc, SceneBase* pScene, D3DXMATRIXA16* pmViewProj,
                                const D3DXVECTOR3* pvCamEyePos,
                                ID3D11RenderTargetView* pRTV, ID3D11DepthStencilView* pDSV, ID3D11UnorderedAccessView* pFragmentLinkUAV, ID3D11UnorderedAccessView* pStartOffsetUAV,
                                ID3D11DepthStencilState* pDepthStencilState, ID3D11Buffer* pFragmentLink, ID3D11Buffer* pStartOffset )
{

    // Clear the start offset buffer by magic value.
    static const UINT clearValueUINT[1] = { 0xffffffff };
    pD3DContext->ClearUnorderedAccessViewUint( pStartOffsetUAV, clearValueUINT );

    // Set UAV
    ID3D11UnorderedAccessView* pUAVs[ 2 ];
    pUAVs[0] = pFragmentLinkUAV;
    pUAVs[1] = pStartOffsetUAV;

    // Initialize UAV counter
    UINT initIndices[] = { 0, 0 };
    pD3DContext->OMSetRenderTargetsAndUnorderedAccessViews( 0, NULL, pDSV, 0, 2, pUAVs, initIndices );

    pD3DContext->OMSetDepthStencilState( pDepthStencilState, 0 );

    pD3DContext->PSSetShader( m_pPS, NULL, 0 );    

    pScene->OnRender( pD3DContext, pmViewProj, pvCamEyePos );

    // Set render target and depth/stencil views to NULL,
    // we'll need to read the RTV in a shader later
    ID3D11RenderTargetView* pViewNULL[ 1 ] = { NULL };
    ID3D11DepthStencilView* pDSVNULL = NULL;
    pD3DContext->OMSetRenderTargets( 1, pViewNULL, pDSVNULL );    

    // for debugging
#if 0
    {
        HRESULT hr;
        ID3D11Buffer* pDebugBuf = CreateAndCopyToDebugBuf( pDevice, pD3DContext, pStartOffset );
        D3D11_MAPPED_SUBRESOURCE MappedResource;     
        V( pD3DContext->Map( pDebugBuf, 0, D3D11_MAP_READ, 0, &MappedResource ) );
        unsigned int* pData = reinterpret_cast< unsigned int* >( MappedResource.pData );
        int nSize = pBackBufferDesc->Width * pBackBufferDesc->Height;
        for( int i=0; i<nSize; ++i ) 
        {
            unsigned int nData = pData[ i ];
            if( nData == 0xFFFFFFFF ) {
                int nBreak = 0;
            }
        }
        pD3DContext->Unmap( pDebugBuf, 0 );
        SAFE_RELEASE( pDebugBuf ); 
    }
#endif

#if 0
    {
        HRESULT hr;
        ID3D11Buffer* pDebugBuf = CreateAndCopyToDebugBuf( pDevice, pD3DContext, pFragmentLink );
        D3D11_MAPPED_SUBRESOURCE MappedResource;     
        V( pD3DContext->Map( pDebugBuf, 0, D3D11_MAP_READ, 0, &MappedResource ) );
        FragmentLink* pData = reinterpret_cast< FragmentLink* >( MappedResource.pData );
        int nSize = pBackBufferDesc->Width * pBackBufferDesc->Height * 8;
        for( int i=0; i<nSize; ++i ) 
        {
            FragmentLink data = pData[ i ];
            if( data.nNext == 0xFFFFFFFF ) {
                int nBreak = 0;
            }
            else {
                int nBreak = 0;
            }
        }
        pD3DContext->Unmap( pDebugBuf, 0 );
        SAFE_RELEASE( pDebugBuf ); 
    }
#endif
}